package cn.stylefeng.guns.modular.business.service.impl;


import cn.stylefeng.guns.base.pojo.node.TreeviewNode;
import cn.stylefeng.guns.base.pojo.node.ZTreeNode;
import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.config.redis.RedisHandler;
import cn.stylefeng.guns.config.redis.redis.util.Redishandler2;
import cn.stylefeng.guns.core.RecoverConst;
import cn.stylefeng.guns.modular.business.common.Constants;
import cn.stylefeng.guns.modular.business.common.GunsData;
import cn.stylefeng.guns.modular.business.entity.Category;
import cn.stylefeng.guns.modular.business.entity.CategoryContent;
import cn.stylefeng.guns.modular.business.mapper.CategoryMapper;
import cn.stylefeng.guns.modular.business.model.result.*;
import cn.stylefeng.guns.modular.business.service.CategoryContentService;
import cn.stylefeng.guns.modular.business.service.CategoryService;
import cn.stylefeng.guns.sys.core.exception.enums.BizExceptionEnum;
import cn.stylefeng.guns.sys.core.util.StringUtils;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Resource
    private CategoryMapper categoryMapper;
    @Autowired
    RedisHandler redisHandler;

    @Autowired
    Redishandler2 redishandler2;

    @Autowired
    private CategoryContentService categoryContentService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addCategory(Category category) {
        if (ToolUtil.isOneEmpty(category, category.getName(), category.getPid())) {
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }
        this.categorySetPidsAndLevel(category);
        if (category.getPid() != 0) {
            List<CategoryTypeView> categoriesType = getCategoriesType();
            categoriesType.forEach(categoryTypeView -> {
                if (category.getPids().contains("[" + categoryTypeView.getCategoryId() + "]")) {
                    category.setCategoryType(categoryTypeView.getCategoryType());
                }
            });
        }
        this.save(category);
        //缓存自己
        redisHandler.getGlobalRedisTemplate().cacheHash(Constants.CATEGORY_SELF_HASH_KEY, "", category.getCategoryId().toString(), JSONObject.toJSONString(category));
        cacheCategory(category);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editCategory(Category category) {
        Category category1 = categoryMapper.selectById(category.getCategoryId());
        if (ToolUtil.isOneEmpty(category, category.getCategoryId(), category.getName())) {
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }
        this.updateById(category);
        //缓存自己
        redisHandler.getGlobalRedisTemplate().cacheHash(Constants.CATEGORY_SELF_HASH_KEY, "", category.getCategoryId().toString(), JSONObject.toJSONString(category));
        cacheCategory(category1);
    }


    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void deleteCategory(Long categoryId) {
        Category category = this.getById(categoryId);
        UpdateWrapper<Category> wrapper = new UpdateWrapper<>();
        if (category.getCategoryId() != null) {
            wrapper.set("DELETE_FLAG", RecoverConst.DEL_FLAG_TRUE).like("PIDS", "%[" + categoryId + "]%");
            List<Category> subDepts = categoryMapper.selectList(wrapper);
            this.update(wrapper);
            /*for (Category temp : subDepts) {
                this.removeById(temp.getCategoryId());
            }*/
        }
        category.setDeleteFlag(RecoverConst.DEL_FLAG_TRUE);
        this.updateById(category);
        //删除自己
        redisHandler.getGlobalRedisTemplate().removeHash(Constants.CATEGORY_SELF_HASH_KEY, "", categoryId.toString());
        cacheCategory(category);
    }

    @Override
    public List<ZTreeNode> tree() {
        return this.baseMapper.tree();
    }

    @Override
    public List<TreeviewNode> treeviewNodes() {
        return this.baseMapper.treeviewNodes();
    }


    @Override
    public Page<Category> list(String condition, String categoryId) {
        Page page = LayuiPageFactory.defaultPage();
        page.setRecords(baseMapper.list(page, condition, categoryId));
        return page;
    }

    private void categorySetPidsAndLevel(Category category) {
        if (ToolUtil.isEmpty(category.getPid()) || category.getPid().equals(0L)) {
            category.setPid(0L);
            category.setPids("[0],");
            category.setLevel(1L);
        } else {
            Long pid = category.getPid();
            Category temp = this.getById(pid);
            String pids = temp.getPids();
            category.setPid(pid);
            category.setPids(pids + "[" + pid + "],");
            category.setLevel((long) Arrays.asList(category.getPids().split(",")).size());
        }
    }

    private void cacheCategory(Category category) {
        Long pid = category.getPid();
        List<Category> categories = categoryMapper.selectList(new QueryWrapper<Category>().eq("DELETE_FLAG", RecoverConst.DEL_FLAG_FALSE)
                .eq("PID", pid).orderByAsc("SORT"));
        redisHandler.getGlobalRedisTemplate().remove(Constants.CATEGORY_KEY, ":" + pid);
        if (CollectionUtils.isNotEmpty(categories)) {
            redisHandler.getGlobalRedisTemplate().cacheStringValue(Constants.CATEGORY_KEY, ":" + pid, JSONArray.toJSONString(categories));
        }
    }

    @Override
    public void initCacheCategories() {
        List<Category> categories = categoryMapper.selectList(new QueryWrapper<Category>().eq("DELETE_FLAG", RecoverConst.DEL_FLAG_FALSE)
                .eq("PID", 0).eq("SELL_STATUS", RecoverConst.CATEGORY_SELL_STATUS_TRUE).orderByAsc("SORT"));
        if (!CollectionUtils.isEmpty(categories)) {
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("0", JSONObject.toJSONString(categories));
            redisHandler.getGlobalRedisTemplate().cacheStringValue(Constants.CATEGORY_KEY, ":" + "0", JSONArray.toJSONString(categories));
            cacheCategoriesToRedis(categories);
            //删除内存中的首页数据
            GunsData.clear();
        }

    }

    @Override
    public Category getCategoryById(Long categoryId) {
        return categoryMapper.selectById(categoryId);
    }

    /**
     * 设置获取方式
     *
     * @param categoryId
     * @param content
     */
    @Override
    public void setContent(Long categoryId, String content) {
        CategoryContent categoryContent = new CategoryContent();
        categoryContent.setCategoryId(categoryId);
        categoryContent.setGetContent(content);
        categoryContentService.saveOrUpdate(categoryContent);
    }

    /**
     * @param categoryId
     * @return
     */
    @Override
    public List<CategoryFrontResultView> getCategoriesWithQuota(Long categoryId) {
        List<CategoryFrontResultView> categoryResultViews = new ArrayList<>();
        String categoryJson = redisHandler.getGlobalRedisTemplate().getStringValue(Constants.CATEGORY_KEY, ":" + categoryId);
        if (categoryJson != null) {
            List<Category> categories = JSONObject.parseArray(categoryJson, Category.class);
            categories.forEach(category -> {
                CategoryFrontResultView categoryResultView = new CategoryFrontResultView();
                categoryResultView.setCategoryId(category.getCategoryId());
                categoryResultView.setName(category.getName());
                categoryResultView.setPicture(category.getPicture());
                categoryResultView.setCategoryType(category.getCategoryType());
                categoryResultView.setRecoverRate(category.getRecoverRate());
                String s = redisHandler.getGlobalRedisTemplate().getStringValue(Constants.CATEGORY_KEY, ":" + category.getCategoryId().toString());
                if (s != null) {
                    List<CategoryFrontResult> categoryList = JSONObject.parseArray(s, CategoryFrontResult.class);
                    for (CategoryFrontResult categoryFrontResult : categoryList) {
                        String listStr = redishandler2.getStringValue(RecoverConst.QUOTA_STR_KEY, categoryFrontResult.getCategoryId().toString());
                        if (StringUtils.isNotEmpty(listStr)) {
                            categoryFrontResult.setQuotaList(JSONArray.parseArray(listStr, CardFrontQuotaResult.class));
                        }
                    }
                    categoryResultView.setCategories(categoryList);
                }
                categoryResultViews.add(categoryResultView);
            });
        }
        return categoryResultViews;
    }

    /**
     * 设置热门
     *
     * @param categoryId
     * @param hot
     * @return
     */
    @Override
    public boolean setHot(Long categoryId, Integer hot) {
        Category category = new Category();
        category.setCategoryId(categoryId);
        category.setHot(hot);
        IndexResult indexResult = GunsData.indexMap.get(Constants.INDEX_MAP_KEY);
        updateById(category);
        indexResult.setHotCardList(null);
        return true;
    }

    /**
     * 设置上下架状态
     *
     * @param categoryId
     * @param sellStatus
     * @return
     */
    @Override
    public boolean setSellStatus(Long categoryId, Integer sellStatus) {
        Category category = new Category();
        category.setCategoryId(categoryId);
        category.setSellStatus(sellStatus);
        updateById(category);
        return true;
    }

    private void cacheCategoriesToRedis(List<Category> categories) {
        //缓存自己
        categories.forEach(category -> {
            redisHandler.getGlobalRedisTemplate().cacheHash(Constants.CATEGORY_SELF_HASH_KEY, "", category.getCategoryId().toString(), JSONObject.toJSONString(category));
            List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().eq("DELETE_FLAG", RecoverConst.DEL_FLAG_FALSE)
                    .eq("PID", category.getCategoryId()).eq("SELL_STATUS", RecoverConst.CATEGORY_SELL_STATUS_TRUE).orderByAsc("SORT"));
            if (CollectionUtils.isNotEmpty(categoryList)) {
                HashMap<String, String> hashMap = new HashMap<>();
                redisHandler.getGlobalRedisTemplate().cacheStringValue(Constants.CATEGORY_KEY, ":" + category.getCategoryId(), JSONArray.toJSONString(categoryList));
                cacheCategoriesToRedis(categoryList);
            }
        });
    }


    @Override
    public List<CategoryResultView> getCategories(Long categoryId, Boolean isAll) {
        List<CategoryResultView> categoryResultViews = new ArrayList<>();
        String categoryJson = redisHandler.getGlobalRedisTemplate().getStringValue(Constants.CATEGORY_KEY, ":" + categoryId);
        if (categoryJson != null) {
            List<Category> categories = JSONObject.parseArray(categoryJson, Category.class);
            categories.forEach(category -> {
                CategoryResultView categoryResultView = new CategoryResultView();
                categoryResultView.setCategoryId(category.getCategoryId());
                categoryResultView.setName(category.getName());
                categoryResultView.setPicture(category.getPicture());
                categoryResultView.setCategoryType(category.getCategoryType());
                categoryResultView.setRecoverRate(category.getRecoverRate());
                categoryResultView.setBackColor(category.getBackColor());
                if (isAll) {
                    String s = redisHandler.getGlobalRedisTemplate().getStringValue(Constants.CATEGORY_KEY, ":" + category.getCategoryId().toString());
                    if (s != null) {
                        List<Category> categoryList = JSONObject.parseArray(s, Category.class);
                        categoryResultView.setCategories(categoryList);
                    }
                }
                categoryResultViews.add(categoryResultView);
            });
        }
        return categoryResultViews;
    }

    @Override
    public List<CategoryTypeView> getCategoriesType() {
        List<CategoryTypeView> categoryTypeViews = new ArrayList<>();
        String s =  redisHandler.getGlobalRedisTemplate().getStringValue(Constants.CATEGORY_KEY, ":" + Constants.CATEGORY_KEY_TOP_ID);
        if (StringUtils.isNotEmpty(s)) {
            List<Category> categoryList = JSONObject.parseArray(s, Category.class);
            for (Category category: categoryList) {
                CategoryTypeView categoryTypeView = new CategoryTypeView();
                categoryTypeView.setCategoryId(category.getCategoryId());
                categoryTypeView.setCategoryType(category.getCategoryType());
                categoryTypeViews.add(categoryTypeView);
            }
        }
        return categoryTypeViews;
    }
}
